<template>
  <div>
    <section class="codemirror-container">
      <editor-tool
        :mode="params.mode"
        :theme="params.theme"
        @share="share"
        @update="openModifyDialog"
        :hideShareBtn="props.id !== ''"
        :enableEdit="!props.options.readOnly && props.id !==''"
        @changeMode="changeMode"
        @changeTheme="changeTheme">
      </editor-tool>
      <div class="textarea-container">
      <textarea
        ref="textarea"
      ></textarea>
      </div>
<!--      <div class="qr-code">-->
<!--        <img src="./qrcode.png" alt="">-->
<!--      </div>-->
    </section>
    <app-dialog
      width="480px"
      v-model:show="showShareDialog"
    >
      <div
        v-loading="generateShareLoading"
      >
        <div class="form-item">
          <span>标题</span>
          <input placeholder="简单描述一下你的代码吧" v-model="params.title">
        </div>
        <div class="form-item">
          <span>密码</span>
          <input placeholder="设置一个访问密码，最多10位" maxlength="10" v-model="params.password">
        </div>
        <div class="form-item">
          <span>过期时间</span>
          <app-select
            plain
            v-model="params.expireAt"
            placeholder="请选择过期时间"
            :data="EXPIRE_AT"
          />
        </div>
        <div class="editable">
          是否允许他人编辑
          <app-switch v-model="params.editable"></app-switch>
        </div>
        <div class="btn-actions">
          <div class="cancel-btn" @click="showShareDialog = false">取消</div>
          <div class="confirm-btn" @click="generateShareUrl">生成分享链接</div>
        </div>
      </div>

    </app-dialog>
    <app-dialog
      width="480px"
      title="分享链接"
      v-model:show="showUrlDialog"
    >
      <div class="share-url-link">{{ getShareLink() }}
        <div
          class="btn-link"
          v-clipboard:copy="getShareLink()"
          v-clipboard:success="copyUrlSuccess"
        >
          {{ copyTitle }}
        </div>
      </div>
      <div class="share-url-tip">请妥善保存分享链接，关闭窗口后无法再次打开相同链接的窗口</div>
      <div class="btn-actions">
        <div class="cancel-btn" @click="closeShowUrlDialog">关闭</div>
      </div>
    </app-dialog>


    <app-dialog
      width="480px"
      v-model:show="showModifyDialog"
    >
      <div>
        <div class="form-item">
          <span>标题</span>
          <input placeholder="简单描述一下你的代码吧" v-model="params.title">
        </div>
        <div class="btn-actions">
          <div class="cancel-btn" @click="showModifyDialog = false">取消</div>
          <div class="confirm-btn" @click="update">确认修改</div>
        </div>
      </div>

    </app-dialog>
  </div>
</template>
<script lang="ts" setup>
import EditorTool from './EditorTool/index.vue'
import * as Codemirror from 'codemirror'
import { CmOptions, CodemirrorInstance, fromTextArea } from 'codemirror'
import { EXPIRE_AT, EXPIRE_AT_HASH } from '@/utils/config'
import codeHistory from '@/hooks/codeHistory'
// console.log(Codemirror.modeInfo)
import { nextTick, onMounted, onUnmounted, provide, reactive, ref, watch, withDefaults } from 'vue'
import { generateUrl, modifyCodeById } from '@/api/code'
const { setCodeTemp, removeCodeTemp, modeHistories, themeHistories } = codeHistory()

window.CodeMirror = Codemirror

interface Props {
  id?: string
  code?: string
  title?: string
  options?: CmOptions
  version?: any
}

let codemirrorInstance: CodemirrorInstance | null = null
provide('codemirrorInstance', {
  get codemirrorInstance() {
    return codemirrorInstance
  }
})

const _options: CmOptions = {
  lineWrapping: 'wrap',
  theme: '',
  mode:'',
  placeholder: '// 使用Ctrl展开提示',
  autofocus: true,
  lineNumbers: true,
  autoCloseBrackets: true,
  readOnly: false,
  extraKeys: {
    'Ctrl': 'autocomplete'
  },
  scrollbarStyle: null
}
const textarea = ref()
const content = ref('')
const props = withDefaults(defineProps<Props>(), {
  id: '',
  title: '',
  code: ``,
  options: () => {
    return {}
  }
})
const emit = defineEmits(['input', 'ready', 'update'])
const params = reactive({
  mode: 'Java',
  theme: 'darcula',
  password: '',
  title: '',
  expireAt: EXPIRE_AT_HASH.never.value,
  editable: false
})


const changeTheme = (theme: any) => {
  params.theme = theme
}
const changeMode = (language: any) => {
  params.mode = language.name
}
const refresh = () => {
  nextTick(() => {
    codemirrorInstance?.refresh()
  })
}
const handlerCodeChange = (newVal: string) => {
  const cmValue = codemirrorInstance?.getValue()
  if (newVal !== cmValue) {
    const scrollInfo = codemirrorInstance?.getScrollInfo() || {
      left: 0,
      top: 0
    }
    codemirrorInstance?.setValue(newVal)
    content.value = newVal
    codemirrorInstance?.scrollTo(scrollInfo.left, scrollInfo.top)
  }
}

const setCurrentTemp = () => {
}

const initialize = () => {
  codemirrorInstance = fromTextArea(textarea.value, getOptions())
  codemirrorInstance.setValue(props.code)
  content.value = codemirrorInstance.getValue()
  codemirrorInstance?.on('change', (cm) => {
    content.value = cm.getValue()
    emit('input', content.value)
  })
  // codemirrorInstance.on('inputRead', function () {
  //   codemirrorInstance?.showHint()
  // })

  emit('ready', codemirrorInstance)
  refresh()
}

const destroy = () => {
  const element = codemirrorInstance?.doc.cm.getWrapperElement()
  element?.remove()
}

onMounted(() => {
  initialize()
})

onUnmounted(() => {
  destroy()
})

const getTruthMode = (mode: string) => {
  if (!mode) {
    return ''
  }
  const language = Codemirror.findModeByName(mode)
  return language?.mime || language?.mode
}

const getOptions = () => {
  const config = {
    ..._options,
    ...props.options
  }
  if (props.options.readOnly) {
    config.extraKeys = {}
    config.placeholder = ''
  }
  params.mode = config.mode || ''
  params.theme = config.theme || ''
  params.title = props.title
  const options = JSON.parse(JSON.stringify(config))
  options.mode = getTruthMode(config.mode || '')
  return options
}

watch(
  () => props.options,
  (options: CmOptions) => {
    const config = getOptions()
    if (!codemirrorInstance) {
      return
    }
    nextTick(()=>{
      console.log(config)
      for (const key in config) {
        codemirrorInstance?.setOption(key, config[key])
      }
    })
  },
  {
    deep: true,
    immediate: true
  }
)
watch(
  () => props.code,
  (val: string) => {
    handlerCodeChange(val)
  }
)


const showShareDialog = ref(false)

const share = () => {
  if (!content.value) {
    return
  }
  showShareDialog.value = true
}
const shareId = ref('')
let generateShareLoading = ref(false)
const copyTitle = ref('复制')
const generateShareUrl = () => {
  if (generateShareLoading.value) {
    return
  }
  generateShareLoading.value = true
  const p = {
    title: params.title,
    syntax: params.mode,
    style: params.theme,
    content: content.value,
    password: params.password,
    expireAt: params.expireAt,
    editable: params.editable
  }
  generateUrl(p).then(({ data }) => {
    shareId.value = data
    showShareDialog.value = false
    showUrlDialog.value = true
  }).finally(() => generateShareLoading.value = false)
}

const showUrlDialog = ref(false)
const getShareLink = () => {
  return `${import.meta.env.VITE_BASE_URL}/${shareId.value}`
}
const copyUrlSuccess = () => {
  copyTitle.value = '已复制'
}
const closeShowUrlDialog = () => {
  showUrlDialog.value = false
  shareId.value = ''
  removeCodeTemp()
}


const showModifyDialog = ref(false)
const openModifyDialog = () => {
  showModifyDialog.value = true
}
const update = () => {
  const data = {
    title: params.title,
    syntax: params.mode,
    style: params.theme,
    content: content.value,
    version: props.version
  }
  modifyCodeById(props.id, data)
    .then((res) => {
      showModifyDialog.value = false
      emit('update')
    })
}
</script>
<style lang="scss" scoped>
@import './index';
</style>
